use super::enhanced_array::EnhancedArray;

/// 从寄存器组s进行比特重组.
///
/// 输出 `(x0, x1, x2, x3)`.
pub fn bit_reconstruct(s: &EnhancedArray<u32, 16>) -> (u32, u32, u32, u32) {
    let x0 = ((s.get(15) << 1) & 0xffff_0000) + (s.get(14) & 0x0000_ffff);

    // `low_to_put_high` 下标的数取低位放高处, `high_to_put_low` 下标的数取高位放低处.
    let high_low_cross = |low_to_put_high: usize, high_to_put_low: usize| {
        (s.get(low_to_put_high) << 16) + (s.get(high_to_put_low) >> 15)
    };
    let x1 = high_low_cross(11, 9);
    let x2 = high_low_cross(7, 5);
    let x3 = high_low_cross(2, 0);
    (x0, x1, x2, x3)
}

mod tests {
    #[test]
    fn test_bit_reconstruct() {
        use super::bit_reconstruct;
        use crate::zuc_encryption::enhanced_array::EnhancedArray;

        let s = [
            0x1ec4d784, 0x2626bc31, 0x25e26b9a, 0x74935ea8, 0x355789de, 0x4135e269, 0x7ef13515,
            0x5709afca, 0x5acd781f, 0x47af136b, 0x326bc4da, 0x0e9af16b, 0x58de26fb, 0x3dbc4dd8,
            0x22f89ac7, 0x2dc7ac66,
        ];
        let s = EnhancedArray::with_array(s);
        let (x0, x1, x2, x3) = bit_reconstruct(&s);
        println!("x: {:x}, {:x}, {:x}, {:x}", x0, x1, x2, x3);
        assert_eq!(x0, 0x5b8f9ac7);
        assert_eq!(x1, 0xf16b8f5e);
        assert_eq!(x2, 0xafca826b);
        assert_eq!(x3, 0x6b9a3d89);
    }
}
